import { Inject, Injectable, UnauthorizedException } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { getRandomStr } from '../utils';
import { CACHE_MANAGER } from '@nestjs/cache-manager';
import { Cache } from 'cache-manager';
import { ConfigService } from '@nestjs/config';

@Injectable()
export class AuthService {
  constructor(
    @Inject(CACHE_MANAGER) private cacheManager: Cache,
    private readonly jwtService: JwtService,
    private configService: ConfigService,
  ) {}

  async validateUser(username: string, password: string): Promise<any> {
    return null;
  }

  /*
        1. 获取redis里signToken
        2. 如果redis的signToken不存在就生成新的，存在就继续使用
        3. 结合signToken生成jwt的token
        4. 如果redis里没有signToken，那么就更新redis；如果有signToken则不处理
        5. verify时用解析出来的signToken和redis里的signToken做对比
    */
  async getToken(userId: string) {
    const sign = getRandomStr(12, false);
    const refreshSign = getRandomStr(12, false);
    const expire = parseInt(this.configService.get('REDIS_USER_EXPIRE'));
    const jwtExpire = parseInt(this.configService.get('JWT_EXPIRE')); // JWT_EXPIRE 单位是秒
    const payload = { userId };
    const accessToken = this.jwtService.sign({ ...payload, sign, type: 1 });
    const refreshToken = this.jwtService.sign(
      { ...payload, sign: refreshSign, type: 2 },
      { expiresIn: expire / 1000 },
    ); // 单位：秒；24小时 * 7

    await this.cacheManager.store.set(
      `${userId}_token`,
      sign,
      jwtExpire * 1000,
    );
    await this.cacheManager.store.set(`${userId}_refresh`, refreshSign, expire);

    return { accessToken, refreshToken };
  }

  async verifyToken(token: string): Promise<any> {
    let userId: any = '';

    try {
      const result = this.jwtService.verify(token);
      userId = result.userId;

      // 校验sign，只要sign不通过就清空token
      const redisKey = `${userId}_${result.type === 1 ? 'token' : 'refresh'}`;
      const sign = await this.cacheManager.store.get(redisKey);
      if (sign && sign === result.sign) return result;

      throw new UnauthorizedException(`请重新登录`);
    } catch (e) {
      // jwt过期
      if (userId) {
        await this.cacheManager.store.del(`${userId}_token`);
        await this.cacheManager.store.del(`${userId}_refresh`);
      }
    }

    return null;
  }
}
